

#include "game_controller.h"
#include <qpixmap.h>
#include <qiconview.h>
#include <qcombobox.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qtoolbutton.h>
#include <qpushbutton.h>
#include <qfiledialog.h> 
#include <qcolordialog.h>
#include <qinputdialog.h>




#include <shellapi.h>

#include <tchar.h>



/*
*
* Game
*
*/
Game::Game (GameController * gc) : controller (gc) {
	model = new DotsGameModel (gc, gc->getFieldWidth (), gc->getFieldHeight ());
	players.clear ();
	currentPlayer = 0;
	startTime = time (0);
}

Game::~Game () {
	delete model;
}


time_t Game::getTimeStart () const {
	return startTime;
}

int Game::getPlayersCount () const {
	return players.size ();
}

int Game::getCurrentPlayer () const {
	return currentPlayer;
}

void Game::setCurrentPlayer (int i) {
	currentPlayer = i;
}

int Game::nextPlayer () {
	currentPlayer++;
	if (currentPlayer >= getPlayersCount())
		currentPlayer = 0;
	return currentPlayer;
}

void Game::removePlayer (int i) {
	players.erase (players.begin() + i);
	if (currentPlayer >= getPlayersCount())
		currentPlayer = 0;
}

PlayerProfile * Game::getPlayer (int i) const {
	if (i < 0 || i >= getPlayersCount())
		return NULL;
	return players.at(i);
}

DotsGameModel * Game::getModel () const {
	return model;
}

int Game::addPlayer (PlayerProfile * p) {
	players.push_back (p);
	return this->getPlayersCount() - 1;
}

void Game::reset () {
	//players.clear ();
	std::vector<PlayerProfile *>::iterator iter;
	for (iter= players.begin(); iter != players.end (); iter++) {
		PlayerProfile * prof = *iter;
		prof->stat.dots = prof->stat.dotsLost = prof->stat.dotsWin = 0;
	}
	currentPlayer = 0;
	if (model)
		delete model;
	model = new DotsGameModel (controller);
	startTime = time (0);
}

GameMoveEvent::GameMoveEvent(Point _p) : QEvent(QEvent::User), _point (_p) {
}

GameMoveEvent::~GameMoveEvent() {
}

QEvent::Type GameMoveEvent::type () const {
	return QEvent::User;
}

Point GameMoveEvent::point () const {
	return _point;
}




/*
*
* GameController
*
*/

int readFromFile (const char * filename, void ** buf) {
	FILE * f = fopen (filename, "rb");
	if (f == NULL)
		return 0;
	fseek (f, 0, SEEK_END);
	int size = ftell (f);
	fseek (f, 0, SEEK_SET);
	*buf = new char [size];
	int r = fread (*buf, 1, size, f);
	fclose (f);
	if (r != size) {
		delete buf;
		return 0;
	}
	return size;
}

char * fromQString (const QString & str) {
	int len = str.length ();
	char * buf = new char [len + 1];
	memset (buf, 0, len + 1);
	strcpy (buf, str.ascii());
	return buf;
}

void GameController::readProfiles (char * fileName) {
	profiles.clear ();
	FILE * f = fopen (fileName, "rb");
	if (f == NULL) {
		saveProfiles (fileName);
		return;
	}
    int count, i;
	if (0 == fread (&count, sizeof (int), 1, f)) {
		saveProfiles (fileName);
		return;
	}
	for (i = 0; i < count; i++) {
		PlayerProfile * p = new PlayerProfile;
		memset (p, 0, sizeof (p));
		p->readFromFile (f);
		profiles.push_back (p);
	}
	fclose (f);
}

void GameController::saveProfiles (char * fileName) {
	FILE * f = fopen (fileName, "wb");
	if (f == NULL) {
		QMessageBox::critical (0, "Error", "Error saving profile!");
		return;
	}
	int count = profiles.size ();
	fwrite (&count, sizeof (int), 1, f);
	PlayerProfilesList::iterator iter;
	for (iter = profiles.begin (); iter != profiles.end (); iter++) {
		PlayerProfile * p = *iter;
		p->writeToFile (f);
	}
	fclose (f);
}

GameController::GameController () : currentGame (NULL), currentProfile (NULL) {
	readProfiles ("profiles.cfg");
	loginDialog = new LoginDialog ();
	loginDialogUpdate ();
	loginDialog->setIcon (QPixmap::fromMimeSource ("images/appicon.png"));
	newUserDialog = new NewUserDialog ();
	newUserDialog->setIcon (QPixmap::fromMimeSource ("images/appicon.png"));
	newGameDialog = new NewGameDialog ();
	newGameDialog->setIcon (QPixmap::fromMimeSource ("images/appicon.png"));
	aboutDialog = new AboutDialog ();
	aboutDialog->setIcon (QPixmap::fromMimeSource ("images/appicon.png"));
	gw = new GameWindow (this);
	gw->setController (this);
	gw->field->init ();
	initConnections ();
	//loggedIn = false;
}

void GameController::initConnections () {
	//From login dialog
	connect (loginDialog->iconView1, SIGNAL ( currentChanged(QIconViewItem *) ), this, SLOT (loginIconChange(QIconViewItem *)));
	connect (loginDialog->toolButton1, SIGNAL ( clicked () ), this, SLOT ( loginNewUser() ));
	//From new-user dialog
	connect (newUserDialog->toolButton4, SIGNAL (clicked ()), this, SLOT (newUserChooseIcon()));
	connect (newUserDialog->pushButton5, SIGNAL (clicked ()), this, SLOT (newUserDefaultIcon()));
	connect (newUserDialog->comboBox1, SIGNAL (activated (const QString &)), this, SLOT (newUserChooseColor(const QString &)));
	//From new-game dialog
	connect (newGameDialog->comboBox1, SIGNAL (activated (const QString &)), this, SLOT (newGamePlayer1Change(const QString &)));
	connect (newGameDialog->comboBox2, SIGNAL (activated (const QString &)), this, SLOT (newGamePlayer2Change(const QString &)));
	connect (newGameDialog->pushButton1, SIGNAL (clicked ()), this, SLOT (newGameNewPlayer1()));
	connect (newGameDialog->pushButton2, SIGNAL (clicked ()), this, SLOT (newGameNewPlayer2()));
	connect (newGameDialog->frame3, SIGNAL (clicked ()), this, SLOT (newGameChangeColorPlayer1()));
	connect (newGameDialog->frame3_2, SIGNAL (clicked ()), this, SLOT (newGameChangeColorPlayer2()));
	//rating
	connect (gw->saveRatingButton, SIGNAL (clicked ()), this, SLOT (ratingSave ()));
	connect (gw->loadRatingButton, SIGNAL (clicked ()), this, SLOT (ratingLoad ()));
	connect (gw->exportRatingButton, SIGNAL (clicked ()), this, SLOT (ratingExport ()));
	connect (gw->closeRatingButton, SIGNAL (clicked ()), this, SLOT (ratingClose ()));

}

GameController::~GameController () {
	delete loginDialog;
	delete newUserDialog;
	delete newGameDialog;
	delete aboutDialog;
	PlayerProfilesList::iterator iter;
	for (iter = profiles.begin (); iter != profiles.end(); iter++)
		delete *iter;
	if (currentGame)
		delete currentGame;
}

void GameController::exec () {
	//int t = 5;
	TRACE ("GameController executed");
	QPixmap pixmap( "images/splash.png" );
	QSplashScreen *splash = new QSplashScreen( pixmap );
	splash->show();
	
	Sleep (1000);	

	splash->finish (loginDialog);

	//silent = true;
	bool done = false;
	while (!done) {
		int result = loginDialog->exec ();
		if (result == QDialog::Accepted) {
			if (loginEnter ())
				break;
			TRACE ("not logged in!");
		} else {
			gameExit ();
		}
	}

	delete splash;
	

	TRACE ("end of exec()");
}

bool GameController::loginEnter () {
	TRACE ("loginEnter()");
	QString name = loginDialog->lineEdit1->text ();
	QString passwd = loginDialog->lineEdit2->text ();
	PlayerProfile * p;
	if (NULL != (p = this->findProfile (name, passwd))) {
		currentProfile = p;
	} else {
		QMessageBox::critical (NULL, "Error!", "Bad player name/password!");
		return false;
	}

	gw->show();
	gw->statusIndicator->hide();
	gw->gameLayout->hide ();
	gw->ratingLayout->hide ();
	gw->gameResetAction->setDisabled (true);
	gw->gameEndForAllAction->setDisabled (true);
	showNewView (gw->emptyLayout);

	//silent = false;
	//loggedIn = true;

	gw->setStatusMessage("Ready.");
	TRACE ("loginEnter() done");
	return true;
}

Game * GameController::getCurrentGame () const {
	return currentGame;
}


void GameController::moveEvent (GameMoveEvent * e) {
	PlayerProfile * profile;
	Move * move;
	int curP = currentGame->getCurrentPlayer();
	profile = currentGame->getPlayer (curP);
	
	move = new Move ();
	move->player = currentGame->getPlayer (curP);
	move->x = e->point().x;
	move->y = e->point().y;
	if (currentGame->getModel()->makeMove (move)) {
		//updata profile statistic
		profile->stat.dots++;
		time_t curTime = time (0);
		time_t newTime = curTime - currentGame->getTimeStart ();
		time_t dt = newTime - profile->stat.timePlayed;
		profile->stat.timePlayed = newTime;
		profile->stat.totalTimePlayed += dt;
		curP = currentGame->nextPlayer ();
		profile = currentGame->getPlayer (curP);
		gw->statusIndicator->setPlayerInfo (profile->name, profile->color);
		gw->statusIndicator->update();
		gw->playersList->updateList ();
		gw->field->update ();
	}
	delete move;
	delete e;

	TRACE ("Updating rating after move...");
	updateRating ();
	TRACE ("Done");
}



//SLOTS


void GameController::gameNew() {
	if (currentGame != NULL) {
		int res = QMessageBox::question (NULL, "Abort", "You are playing a game now. "
			"Creating new game will abort it. Would you like to continue?", QMessageBox::Yes, QMessageBox::No);
		if (res == QMessageBox::Yes) {
			//silent = true;
			gameEndForAll ();
		} else
			return;
	} 
	
	//showDialog and ask for players
	
	newGameDialog->comboBox1->clear ();
	newGameDialog->comboBox2->clear ();
	//addplayers
	PlayerProfilesList::iterator iter;
	for (iter = profiles.begin(); iter != profiles.end(); iter++) {
		PlayerProfile * pp = *iter;
		newGameDialog->comboBox1->insertItem (pp->name);
		newGameDialog->comboBox2->insertItem (pp->name);
	}

	newGameDialog->comboBox1->setCurrentText (currentProfile->name);
	newGameDialog->comboBox1->setEnabled (false);
	newGameDialog->pushButton1->setEnabled (false);
	newGameDialog->comboBox2->setCurrentText (currentProfile->name);
	newGameDialog->comboBox2->setEnabled (true);
	newGameDialog->pushButton2->setEnabled (true);

	newGamePlayer1Change (newGameDialog->comboBox1->currentText ());
	newGamePlayer2Change (newGameDialog->comboBox2->currentText ());

	PlayerProfile * profile1, *profile2;
	while (true) {
		if (newGameDialog->exec () == QDialog::Rejected) {
			return;
		}
		QString player1name = newGameDialog->comboBox1->currentText ();
		QString player2name = newGameDialog->comboBox2->currentText ();
		profile1 = findProfile (player1name, NULL, true);
		profile2 = findProfile (player2name, NULL, true);
		if ((profile1 == NULL)||(profile2 == NULL)||(profile1->id == profile2->id)) {
			QMessageBox::critical (NULL, "Error", "Please select different player profiles!");
			continue;
		}
		break;
	}

	profile1->stat.dots = profile1->stat.dotsLost = profile1->stat.dotsWin = 0;
	profile2->stat.dots = profile2->stat.dotsLost = profile2->stat.dotsWin = 0;
	profile1->stat.timePlayed = profile2->stat.timePlayed = 0;

	currentGame = new Game (this);
	currentGame->addPlayer (profile1);
	currentGame->addPlayer (profile2);
	

	gw->gameResetAction->setDisabled (false);
	gw->gameEndForAllAction->setDisabled (false);
	gw->playersList->updateList ();
	showNewView (gw->gameLayout);
	gw->field->updateGeometry ();
	gw->field->repaint ();

	PlayerProfile * cProfile = currentGame->getPlayer (currentGame->getCurrentPlayer());
	if (cProfile)
		gw->statusIndicator->setPlayerInfo (cProfile->name, cProfile->color);
	else
		qWarning ("gameNew() : NULL CURRENT PLAYER!");
}


void GameController::gameEndForCurrent() {
	// fool method
}


void GameController::gameEndForAll() {
	int res = QMessageBox::question (NULL, "Confirmation", 
		"Are you sure want to end game?", QMessageBox::Yes, QMessageBox::No);
	if (res == QMessageBox::No)
		return;
	saveProfiles ("profiles.cfg");
	delete currentGame;
	currentGame = 0;
	gw->gameResetAction->setDisabled (true);
	gw->gameEndForAllAction->setDisabled (true);
	while (showPreviousView ())
		;
    showNewView (gw->emptyLayout);
}

void GameController::gameReset() {
	if (!currentGame)
		return;
	int res = QMessageBox::question (NULL, "Confirmation", 
		"Are you sure want to continue?", QMessageBox::Yes, QMessageBox::No);
	if (res == QMessageBox::No)
		return;
	currentGame->reset();
	gw->playersList->updateList ();
	gw->field->update();
	PlayerProfile * profile = currentGame->getPlayer (currentGame->getCurrentPlayer());
	gw->statusIndicator->setPlayerInfo (profile->name, QColor (profile->color));
}

void GameController::gameSettings() {
	newUserDefaultIcon ();
	newUserDialog->lineEdit1->setText (currentProfile->name);
	newUserDialog->lineEdit2->setText (currentProfile->passwd);
	newUserDialog->frame4->setBackgroundColor (QColor(currentProfile->color));
	switch (currentProfile->color) {
		case 0xffffffff:
			newUserDialog->comboBox1->setCurrentText ("Black");
			break;
		case 0xffff0000:
			newUserDialog->comboBox1->setCurrentText ("Red");
			break;
		case 0xff00ff00:
			newUserDialog->comboBox1->setCurrentText ("Green");
			break;
		case 0xff0000ff:
			newUserDialog->comboBox1->setCurrentText ("Blue");
			break;
		case 0xffffff00:
			newUserDialog->comboBox1->setCurrentText ("Cyan");
			break;
		case 0xffff00ff:
			newUserDialog->comboBox1->setCurrentText ("Magenta");
			break;
		case 0xff00ffff:
			newUserDialog->comboBox1->setCurrentText ("Yellow");
			break;
		default:
			//QMessageBox::information (0, "", QString ("%1").arg ((uint)currentProfile->color));
			newUserDialog->comboBox1->setCurrentText ("Custom...");
	};
	QPixmap icon;
	icon.loadFromData ((const uchar *)currentProfile->userPic, currentProfile->userPicSize);
	newUserDialog->pixmapLabel2->setPixmap (icon);
	bool done = false;
	while (!done) {
		if (newUserDialog->exec () == QDialog::Rejected) {
			return;
		}
		//check, that all field are correctly filled
		if (newUserDialog->lineEdit1->text ().length () == 0) {
			QMessageBox::critical (NULL, "Error", "Please, fill in player name!");
			continue;
		}
		QPixmap newIcon = QPixmap::grabWidget (newUserDialog->pixmapLabel2);
		if (newIcon.save ("tmp.png", "PNG")) {
			delete currentProfile->userPic;
			currentProfile->userPicSize = readFromFile ("tmp.png", &(currentProfile->userPic));
		} else
			qWarning ("Couldn't save pixmap");
		currentProfile->name = fromQString (newUserDialog->lineEdit1->text ());
		currentProfile->passwd = fromQString (newUserDialog->lineEdit2->text ());
		currentProfile->color = newUserDialog->frame4->backgroundColor ().rgb ();
		saveProfiles ("profiles.cfg");
		done = true;
	}
}

void GameController::gameExit() {
	TRACE ("gameExit()");
	if (currentGame) {
		int res = QMessageBox::question( NULL, "Exit",
			"You are now playing a game. Exit will abort the game. "
			"Are sure want to exit?", QMessageBox::Yes, QMessageBox::No);
		if (res == QMessageBox::No)
			return;
	}
	this->saveProfiles ("profiles.cfg");
	QApplication::exit(0);
	exit (0);
}

void GameController::infoRating() {	
	// fill	in rating
	TRACE ("Showing rating");
	Rating rating;
	rating.readFromFile	("rating.dat");
	TRACE ("Rating loaded. %d items", rating.itemCount);
	for	(int i = 0;	i <	gw->ratingTable->numRows ()	- 1; i++) {
		TRACE ("Filling %d-th line.", i);
		if (i >= rating.itemCount) {
			TRACE ("No rating item here");
			gw->ratingTable->setText (i, 0,	"");
			gw->ratingTable->setText (i, 1,	"");
			gw->ratingTable->setText (i, 2,	"");
			gw->ratingTable->setText (i, 3,	"");
			continue;
		}
		char tmp[255];
		gw->ratingTable->setText (i, 0,	rating.items[i].name);
		memset (tmp, 0, sizeof (tmp));
		sprintf (tmp, "%d", rating.items[i].stat.totalDotsWin);
		gw->ratingTable->setText (i, 1,	tmp);
		memset (tmp, 0, sizeof (tmp));
		sprintf (tmp, "%d", rating.items[i].stat.totalDotsLost);
		gw->ratingTable->setText (i, 2,	tmp);
		memset (tmp, 0, sizeof (tmp));
		sprintf (tmp, "%d:%d", rating.items[i].stat.totalTimePlayed/60, rating.items[i].stat.totalTimePlayed%60);
		gw->ratingTable->setText (i, 3,	tmp);
	}
	showNewView (gw->ratingLayout);
}

void GameController::helpContents() {
	ShellExecute (NULL, NULL, _T("data\\help.html"), NULL, NULL, SW_SHOWDEFAULT);
}

void GameController::helpRules() {
	TRACE ("trying to launch help rules");
	ShellExecute (NULL, NULL, _T("data\\rules.html"), NULL, NULL, SW_SHOWDEFAULT);
	
}

void GameController::helpAbout() {
	aboutDialog->exec ();
}

//events from game model, TODO!!!!!!!
void GameController::push (Event * e) {
	TRACE ("Notify from model. data = %p, size = %d, player = %p", e->data, e->size, e->player);
	//QMessageBox::information (0, "WOn!", "I've won a dot!");
	Point * p = (Point*)e->data;
	TRACE ("Point = %d,%d", p->x, p->y);
	TRACE ("Modifiing stat");
	e->player->stat.dotsWin++;
	e->player->stat.totalDotsWin++;
	e->player->stat.dots++;
	e->old->stat.dotsLost++;
	e->old->stat.totalDotsLost++;
	e->old->stat.dots--;
	TRACE ("Saving profiles");
	saveProfiles ("profiles.cfg");
	/*TRACE ("Updating rating");
	updateRating ();*/
	TRACE ("Done");
}

//From login dialog
void GameController::loginIconChange (QIconViewItem * item) {
	QString name = item->text ();
	loginDialog->lineEdit1->setText (name);
	loginDialog->lineEdit2->clear ();
	// TODO: add check for already entered username
}

void GameController::loginNewUser () {	
	//newUserDialog->show ();
	PlayerProfile * pr = createNewProfile ();
	if (pr == NULL)
		return;
	profiles.push_back (pr);
	saveProfiles ("profiles.cfg");
	loginDialogUpdate ();
}

//From new-user dialog
void GameController::newUserChooseIcon () {
	QFileDialog * fDlg = new QFileDialog (".", "Images (*.png *.jpg *.jpeg *.bmp *.gif)");
	if (fDlg->exec () != QDialog::Rejected) {
		QString fName = fDlg->selectedFile ();
		QPixmap icon;
		icon.load (fName);
		newUserDialog->pixmapLabel2->setPixmap (icon);
	}
	delete fDlg;
}

void GameController::newUserDefaultIcon () {
	newUserDialog->pixmapLabel2->setPixmap(QPixmap::fromMimeSource ("./images/defaultuserpic.png"));
}

void GameController::newUserChooseColor (const QString & string) {
	if (string.startsWith ("Custom")) {
		QColor col = QColorDialog::getColor (newUserDialog->frame4->backgroundColor (), newUserDialog, 
			"color dialog");
		if (col.isValid ()) {
			newUserDialog->frame4->setBackgroundColor(col.rgb());
		}
	} else {
		newUserDialog->frame4->setBackgroundColor(string.lower());
	}
}

//From new-game dialog
void GameController::newGamePlayer1Change (const QString & string) {
	PlayerProfile * prof = findProfile (string, "", true);
	if (strlen(prof->passwd) && prof != currentProfile) {
		// check password
		bool ok;
		QString text = QInputDialog::getText(
			"Password", "This profile is password protected. Password:", QLineEdit::Password,
            QString::null, &ok);
		if (ok && !text.isEmpty() && (strcmp (text.ascii(),prof->passwd)==0)) {
			newGameDialog->frame3->setPaletteBackgroundColor (QColor(prof->color));
		} else {
			if (ok && !text.isEmpty() && (strcmp (text.ascii(),prof->passwd) != 0))
				QMessageBox::critical (newGameDialog, "Error", "Incorrect password!");
			newGameDialog->comboBox1->setCurrentText (currentProfile->name);
			return;
		}
	}
	else newGameDialog->frame3->setPaletteBackgroundColor (QColor(prof->color));
}

void GameController::newGamePlayer2Change (const QString & string) {
	PlayerProfile * prof = findProfile (string, "", true);
	if (strlen(prof->passwd) && prof != currentProfile) {
		// check password
		bool ok;
		QString text = QInputDialog::getText(
			"Password", "This profile is password protected. Password:", QLineEdit::Password,
            QString::null, &ok);
		if (ok && !text.isEmpty() && (strcmp (text.ascii(),prof->passwd)==0)) {
			newGameDialog->frame3_2->setPaletteBackgroundColor (QColor(prof->color));
		} else {
			if (ok && !text.isEmpty() && (strcmp (text.ascii(),prof->passwd) != 0))
				QMessageBox::critical (newGameDialog, "Error", "Incorrect password!");
			newGameDialog->comboBox2->setCurrentText (currentProfile->name);
			return;
		}
	}
	else newGameDialog->frame3_2->setPaletteBackgroundColor (QColor(prof->color));


	//newGameDialog->frame3_2->setPaletteBackgroundColor (QColor(prof->color));
}

void GameController::newGameNewPlayer1 () {
	PlayerProfile * pr = createNewProfile ();
	if (pr == NULL)
		return;
	profiles.push_back (pr);
	saveProfiles ("profiles.cfg");
	newGameDialog->comboBox1->insertItem (pr->name);
	newGameDialog->comboBox2->insertItem (pr->name);
	newGameDialog->comboBox1->setCurrentText (pr->name);
	newGamePlayer1Change (newGameDialog->comboBox1->currentText ());
}

void GameController::newGameNewPlayer2 () {
	PlayerProfile * pr = createNewProfile ();
	if (pr == NULL)
		return;
	profiles.push_back (pr);
	saveProfiles ("profiles.cfg");
	newGameDialog->comboBox1->insertItem (pr->name);
	newGameDialog->comboBox2->insertItem (pr->name);
	newGameDialog->comboBox2->setCurrentText (pr->name);
	newGamePlayer2Change (newGameDialog->comboBox2->currentText ());

}

void GameController::newGameChangeColorPlayer1 () {
	PlayerProfile * p = findProfile (newGameDialog->comboBox1->currentText(), "", true);
	QColor col = QColorDialog::getColor (newUserDialog->frame4->backgroundColor (), newGameDialog);
	if (col.isValid ()) {
		newGameDialog->frame3->setBackgroundColor(col.rgb());
		p->color = col.rgb();
		saveProfiles ("profiles.cfg");
	}
}

void GameController::newGameChangeColorPlayer2 () {
	PlayerProfile * p = findProfile (newGameDialog->comboBox1->currentText(), "", true);
	QColor col = QColorDialog::getColor (newUserDialog->frame4->backgroundColor (), newGameDialog);
	if (col.isValid ()) {
		newGameDialog->frame3_2->setBackgroundColor(col.rgb());
		p->color = col.rgb();
		saveProfiles ("profiles.cfg");
	}
}

PlayerProfile * GameController::findProfile (QString _name, QString _passwd, bool _ignorePasswd) {
	PlayerProfile * res = 0;
	PlayerProfilesList::iterator iter;
	for (iter = profiles.begin(); iter != profiles.end (); iter++) {
		PlayerProfile * t = *iter;
		if ((_name == t->name)&&(_ignorePasswd || (_passwd == t->passwd))) {
			res = t;
			break;
		}
	}
	return res;
}

void GameController::loginDialogUpdate () {
	loginDialog->iconView1->clear ();
	PlayerProfilesList::iterator iter;
	for (iter = profiles.begin(); iter != profiles.end (); iter++) {
		PlayerProfile * p = *iter;
		QPixmap icon;
		icon.loadFromData ((uchar *)p->userPic, p->userPicSize);
		QIconViewItem * item = new QIconViewItem (loginDialog->iconView1, loginDialog->iconView1->lastItem(), p->name, icon);
		loginDialog->iconView1->insertItem (item);
	}
}

PlayerProfile * GameController::createNewProfile () {
	newUserDefaultIcon ();
	newUserDialog->lineEdit1->clear ();
	newUserDialog->lineEdit2->clear ();
	newUserDialog->comboBox1->setCurrentItem(0);
	newUserDialog->frame4->setBackgroundColor (QColor (newUserDialog->comboBox1->currentText()));
	bool done = false;
	while (!done) {
		if (newUserDialog->exec () == QDialog::Rejected) {
			return NULL;
		}
		// check
		if (newUserDialog->lineEdit1->text ().length () == 0) {
			QMessageBox::critical (NULL, "Error", "Please, fill in player name!");
			continue;
		}
		if (NULL != findProfile (newUserDialog->lineEdit1->text (), "", true)) {
			QMessageBox::critical (NULL, "Error", "Player with such name already exists. Please enter another.");
			continue;
		}
		PlayerProfile * pr = new PlayerProfile ();
		memset (pr, 0, sizeof (pr));
		memset (&pr->stat, 0, sizeof (GameStatistic));
		//QPixmap * newIcon = newUserDialog->pixmapLabel2->pixmap ();
		//newIcon->resize (64, 64);
		QPixmap newIcon = QPixmap::grabWidget (newUserDialog->pixmapLabel2);
		if (newIcon.save ("tmp.png", "PNG")) {
			delete pr->userPic;
			pr->userPicSize = readFromFile ("tmp.png", &(pr->userPic));
		} else
			qWarning ("Couldn't save pixmap");
		pr->name = fromQString (newUserDialog->lineEdit1->text ());
		pr->passwd = fromQString (newUserDialog->lineEdit2->text ());
		pr->color = newUserDialog->frame4->backgroundColor ().rgb(); ///!!!
		int maxID = 0;
		PlayerProfilesList::iterator iter;
		for (iter = profiles.begin (); iter != profiles.end (); iter++) {
			if ((*iter)->id > maxID)
				maxID = (*iter)->id;
		}
		pr->id = maxID + 1;
		return pr;
	}
	return NULL;
}


void GameController::ratingSave () {
	QFileDialog * fDlg = new QFileDialog (".", "Data files (*.dat)");
	fDlg->setMode (QFileDialog::AnyFile);
	try {
		if (fDlg->exec () != QDialog::Rejected) {
			QString fName = fDlg->selectedFile ();
			if (!fName.endsWith (".dat"))
				fName += ".dat";
			Rating rating;
			rating.readFromFile	("rating.dat");
			rating.writeToFile (fName.ascii ());
			QMessageBox::information (0, "Done", "Succesfully saved");
		}
	} catch (...) {
		QMessageBox::critical (0, "Error", "Coundn't save rating!");
	}
	delete fDlg;
}

void GameController::ratingLoad () {
	QFileDialog * fDlg = new QFileDialog (".", "Data files (*.dat)");
	try {
		if (fDlg->exec () != QDialog::Rejected) {
			QString fName = fDlg->selectedFile ();
			Rating rating;
			rating.readFromFile	(fName.ascii ());
			rating.writeToFile ("rating.dat");
			this->infoRating ();
		}
	} catch (...) {
		QMessageBox::critical (0, "Error", "Coundn't load rating!");
	}
	delete fDlg;
}

//TODO: fixit
void GameController::ratingExport () {
	QFileDialog * fDlg = new QFileDialog (".", "Html files (*.html)");
	fDlg->setMode (QFileDialog::AnyFile);
	try {
		if (fDlg->exec () != QDialog::Rejected) {
			QString fName = fDlg->selectedFile ();
			if (!fName.endsWith (".html"))
				fName += ".html";
			FILE * f = fopen (fName.ascii (), "wt");
			fprintf (f, 
				"<html>"
				"<head><title>Rating</title>"
				"<link rel=\"stylesheet\" type=\"text/css\" href=\"data/style.css\">"
				"</head>"
				"<body>\n<h1>The Dots Rating</h1>"
				"<table border=1 cellspacing=0 cellpadding=5>\n");
			fprintf (f, "<tr><th>Place</th><th>Name</th><th>Won dots</th><th>Lost dots</th><th>Time played (in min)</th></tr>\n");
			Rating rating;
			rating.readFromFile	("rating.dat");
			for	(int i = 0;	i <	gw->ratingTable->numRows (); i++) {
				if (i >= rating.itemCount) {
					fprintf (f, "<tr><td>%d</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>\n", i + 1);
					continue;
				}
				fprintf (f, "<tr><td>%d</td><td>%s</td><td>%d</td><td>%d</td><td>%d:%d</td></tr>\n", 
					i + 1, rating.items[i].name, rating.items[i].stat.totalDotsWin, 
					rating.items[i].stat.totalDotsLost, rating.items[i].stat.totalTimePlayed/60, rating.items[i].stat.totalTimePlayed%60);
			}
			fprintf (f, "</table></body></html>\n");
			fclose (f);
			QMessageBox::information (0, "Done", "Succesfully saved");
		} 
	} catch (...) {
		QMessageBox::critical (0, "Error", "Coundn't export rating!");
	}
	delete fDlg;
}

void GameController::ratingClose () {
	showPreviousView ();
}

QWidget * GameController::showPreviousView () {
	QWidget * cur = gw->centralWidget ();
	cur->hide ();
	if (cur == gw->gameLayout) {
		gw->statusIndicator->hide ();
	}
	if (viewStack.empty ())
		return 0;
	QWidget * w = viewStack.top ();
	viewStack.pop ();
	w->show ();
	gw->setCentralWidget (w);
	return cur;
}

void GameController::showNewView (QWidget * w) {
	QWidget * cur = gw->centralWidget ();
	if (cur == w)
		return;
	viewStack.push (cur);
	cur->hide ();
	w->show ();
	gw->setCentralWidget (w);
	if (w == gw->gameLayout) {
		gw->statusIndicator->show ();
	}
}



bool GameController::ratingCmpFunc (const RatingItem & i1, const RatingItem & i2) {
	return i1.stat.totalDotsWin >= i2.stat.totalDotsWin;
}

void GameController::updateRating () {
	TRACE ("updateRating ()");
	int i;
	Rating rating;
	rating.readFromFile ("rating.dat");
	std::vector <RatingItem> items;

	PlayerProfilesList::iterator iter;
	for (iter = profiles.begin (); iter != profiles.end (); iter++) {
		PlayerProfile * p = *iter;
		RatingItem it;
		it.name = p->name;
		it.stat = p->stat;
		TRACE ("User %s", p->name);
		//search for an item
		int ind = -1;
		for (i = 0; i < rating.itemCount; i++) {
			TRACE ("%d %s %s", i, p->name, rating.items[i].name);
			if (strcmp(rating.items[i].name, p->name) == 0)  {
				ind = i;
				break;
			}
		}
		if (ind != -1) { //already exists
			TRACE ("User already exists");
			rating.items[ind].stat = p->stat;
		} else {
			TRACE ("Adding as new user");
			items.push_back (it);
		}
	}

	TRACE ("Dropping all existing users");
	for (i = 0; i < rating.itemCount; i++)
		items.push_back (rating.items [i]);

	TRACE ("Sorting");
	std::sort (items.begin (), items.end (), ratingCmpFunc);

	TRACE ("Filling in");
	std::vector<RatingItem>::iterator iter2;
	int k;
	for (k = 0, iter2 = items.begin (); (iter2 != items.end ())&&(k < 10); iter2++, k++) {
		RatingItem it = *iter2;
		rating.items[k] = it;
	}

	rating.itemCount = (items.size () > 10)?10:items.size ();
	rating.writeToFile ("rating.dat");
	TRACE ("Rating updated");
}

void GameController::gameGlobalSettings() {
	bool ok;
    int res = QInputDialog::getInteger(
            "Field size", "Size", getFieldWidth (), 10, 35, 1, &ok);
    if ( ok ) {
        // user entered something and pressed OK
		QMessageBox::information (0, "Done", "Saved. New settings will be applyed on next game.");
		setFieldSize (res, res);
    } else {
        // user pressed Cancel
		return;
    }
}

void GameController::gameLogout() {
	if (currentGame) {
		int res = QMessageBox::question( NULL, "Exit",
			"You are now playing a game. Exit will abort the game. "
			"Are sure want to exit?", QMessageBox::Yes, QMessageBox::No);
		if (res == QMessageBox::No)
			return;
		delete currentGame;
		currentGame = 0;
	
	}
	this->saveProfiles ("profiles.cfg");

	/*while (showPreviousView ())
		;
	gw->gameResetAction->setDisabled (true);
	gw->gameEndForAllAction->setDisabled (true);
	gw->hide ();*/

	//deinit
	delete gw;
	delete loginDialog;
	delete newUserDialog;
	delete newGameDialog;
	delete aboutDialog;
	PlayerProfilesList::iterator iter;
	for (iter = profiles.begin (); iter != profiles.end(); iter++)
		delete *iter;
	if (currentGame)
		delete currentGame;

	//init
	readProfiles ("profiles.cfg");
	loginDialog = new LoginDialog ();
	loginDialogUpdate ();
	newUserDialog = new NewUserDialog ();
	newGameDialog = new NewGameDialog ();
	aboutDialog = new AboutDialog ();
	gw = new GameWindow (this);
	gw->setController (this);
	initConnections ();

	this->exec ();
}

int GameController::getFieldWidth () {
	FILE * f = fopen ("settings.cfg", "rb");
	if (f == NULL) {
		setFieldSize (20, 20);
		return 20;
	}
	int x = 20;
	fread (&x, sizeof (int), 1, f);
	fclose (f);
	return x;
}

int GameController::getFieldHeight () {
	FILE * f = fopen ("settings.cfg", "rb");
	if (f == NULL) {
		setFieldSize (20, 20);
		return 20;
	}
	int x = 20;
	fread (&x, sizeof (int), 1, f);
	fread (&x, sizeof (int), 1, f);
	fclose (f);
	return x;
}

void GameController::setFieldSize (int x, int y) {
	FILE * f = fopen ("settings.cfg", "wb");
	if (f == NULL)
		return;
	fwrite (&x, sizeof (int), 1, f);
	fwrite (&y, sizeof (int), 1, f);
	fclose (f);
}

